package com.longkey.workflow.client.canvas
{
	import com.longkey.workflow.client.constants.AnchorType;
	import com.longkey.workflow.client.constants.ElementType;
	import com.longkey.workflow.client.constants.StatusType;
	import com.longkey.workflow.client.event.PropertyEvent;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.EventPhase;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.getQualifiedClassName;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.core.DragSource;
	import mx.core.UIComponent;
	import mx.events.CloseEvent;
	import mx.events.DragEvent;
	import mx.graphics.SolidColor;
	import mx.graphics.SolidColorStroke;
	import mx.managers.DragManager;
	import mx.utils.UIDUtil;
	
	import spark.components.BorderContainer;
	import spark.components.Group;
	import spark.components.Scroller;
	import spark.layouts.BasicLayout;
	import spark.layouts.HorizontalLayout;
	import spark.layouts.VerticalLayout;
	import spark.primitives.Rect;

	public class WFCanvas extends BorderContainer
	{
		private var startNode:WorkNode;
		private var endNode:WorkNode;
		
		private var elements:ArrayCollection;
		
		public var status:int = StatusType.NOP;
		
		public var movingEles:ArrayCollection;
		public var resizingNode:WorkNode;
		public var currentElement:BaseElement;
		
		public var cursor:String = MouseCursor.AUTO;
		
		private static var subProcessDefaultNamePtn:RegExp = new RegExp("^子流程(\\d+)$");
		private static var normalTaskDefaultNamePtn:RegExp = new RegExp("^任务(\\d+)$");
		

		//表现层子元素
		protected var selectStartPoint:Point;
		protected var selectRect:Rect;
		public var controlbar:WFControlBar;
		protected var scroller:Scroller;
		protected var diagramGroup:Group;
		protected var diagram:BorderContainer;
		
		public var tempElement:BaseElement;
		protected var tempStart:WorkNode;
		protected var tempEnd:WorkNode;
		protected var tempTask:WorkNode;
		protected var tempProc:WorkNode;
		public var tempLink:FlowLink;
		
		protected var diagramClickSkip:Boolean = false;
		
		public function WFCanvas()
		{
			super();
			this.status = StatusType.CANVAS_NORMAL;
			init();
//			createTestElements();
		}
		
		private function init():void{
			this.percentWidth = 100;
			this.percentHeight = 100;
			var vt:VerticalLayout = new VerticalLayout();
			vt.gap = 0;
			this.layout = vt;
			
			this.elements = new ArrayCollection();
			this.resizingNode = null;
			this.movingEles = new ArrayCollection();
			
			this.initControlbar();
			this.initDiagram();
			
		}
		
		private function initControlbar():void{
			this.controlbar = new WFControlBar(this);
			this.addElement(this.controlbar);
		}
		
		private function initDiagram():void{
			this.diagram = new BorderContainer();
			var ss:SolidColorStroke = new SolidColorStroke();
			ss.alpha = 0;
			ss.weight = 0;
			this.diagram.borderStroke = ss;
			this.diagram.layout = new BasicLayout();
			this.diagram.percentHeight = 100;
			this.diagram.percentWidth = 100;
			
			this.selectStartPoint = new Point();
			this.selectRect = new Rect();
			this.selectRect.alpha = 1;
			this.selectRect.depth = 9;
			this.selectRect.visible = false;
			var stk:SolidColorStroke = new SolidColorStroke(0x0, 1, 1);
			this.selectRect.stroke = stk;
			this.selectRect.fill = new SolidColor(0x00ff00, 0.1);
			this.diagram.addElement(this.selectRect);
			
			this.diagram.addEventListener(DragEvent.DRAG_ENTER, diagramDragEnterHandler);
			this.diagram.addEventListener(DragEvent.DRAG_DROP, diagramDragDropHandler);
			this.diagram.addEventListener(MouseEvent.CLICK, diagramMouseClickHandler);
			this.diagram.addEventListener(MouseEvent.MOUSE_UP, diagramMouseUpHandler);
			this.diagram.addEventListener(MouseEvent.MOUSE_MOVE, diagramMouseMoveHandler);
			this.diagram.addEventListener(MouseEvent.MOUSE_DOWN, diagramMouseDownHandler);
			this.diagram.addEventListener(MouseEvent.MOUSE_OUT, diagramMouseOutHandler);
			this.diagram.addEventListener(MouseEvent.MOUSE_OVER, diagramMouseOverHandler);
			
			this.diagram.addEventListener(Event.ADDED_TO_STAGE, diagramAddToStageHandler);

			this.diagramGroup = new Group();
			this.diagramGroup.percentHeight = 100;
			this.diagramGroup.percentWidth = 100;
			diagramGroup.addElement(this.diagram);
			
			this.scroller = new Scroller();
			scroller.percentHeight = 100;
			scroller.percentWidth = 100;
			scroller.viewport = this.diagramGroup;

			this.addElement(scroller);	
			
			this.initTempElements();
		}
		
		private function diagramAddToStageHandler(event:Event):void{
			this.diagram.stage.addEventListener(KeyboardEvent.KEY_UP, diagramKeyUpHandler);
		}
		
		private function initTempElements():void{
			this.tempStart = new WorkNode(ElementType.START);
			tempStart.visible = false;
			tempStart.depth = 5;
			this.addDiagramElement(tempStart, true);
			
			this.tempEnd = new WorkNode(ElementType.END);
			tempEnd.visible = false;
			tempEnd.depth = 5;
			this.addDiagramElement(tempEnd, true);
			
			this.tempTask = new WorkNode(ElementType.TASK);
			tempTask.visible = false;		
			tempTask.depth = 5;
			this.addDiagramElement(tempTask, true);
			tempTask.name = "任务";
			
			this.tempProc = new WorkNode(ElementType.PROC);
			tempProc.visible = false;			
			tempProc.depth = 5;
			this.addDiagramElement(tempProc, true);
			tempProc.name = "子流程";
			
			this.tempLink = new FlowLink();
			this.tempLink.status = StatusType.LINE_SAMPLE;
			this.tempLink.isTemp = true;
			this.tempLink.visible = false;
			this.tempLink.depth = 5;
			this.addDiagramElement(tempLink, true);
		}
		
		protected function diagramMouseDownHandler(event:MouseEvent):void{	
			var p:Point = this.getDiagramPoint(event);
			this.currentElement = this.getPointElement(p);
			if(this.currentElement != null && this.currentElement.type == ElementType.LINK){
				var link:FlowLink = this.currentElement as FlowLink;
			}
			switch(this.status){
				case StatusType.CANVAS_NORMAL:
					if(currentElement == null){
						this.selectStartPoint.x = p.x;
						this.selectStartPoint.y = p.y;
						this.status = StatusType.CANVAS_SELECT_RECT;
						this.selectRect.width = 0;
						this.selectRect.height = 0;
						this.selectRect.visible = true;
					}
					break;
				default:
					break;
			}
		}
		
		protected function diagramMouseOverHandler(event:MouseEvent):void{
			if(this.tempElement != null){
				this.tempElement.visible = false;
			}
			this.tempElement == null;
			switch(this.status){
				case StatusType.CANVAS_CREATE_ELEMENT:
					switch(this.controlbar.createElementType){
						case ElementType.START:
							this.tempElement = this.tempStart;
							break;
						case ElementType.END:
							this.tempElement = this.tempEnd;
							break;
						case ElementType.TASK:
							this.tempElement = this.tempTask;
							break;
						case ElementType.PROC:
							this.tempElement = this.tempProc;
							break;
						case ElementType.LINK:
							this.tempElement = this.tempLink;
							break;
						default:
							break;
					}
					break;
				default:
					break;
			}
			var p:Point = this.getDiagramPoint(event);
			if(this.tempElement != null){
				this.tempElement.visible = true;
				this.tempElement.skin.currentState = "sample";
				if(this.tempElement.type == ElementType.LINK){
					this.tempLink.mousePoint = p;
				}
				else{
					this.tempElement.x = p.x - this.tempElement.width/2;
					this.tempElement.y = p.y - this.tempElement.height/2;
				}
			}
		}
		
		protected function diagramMouseOutHandler(event:MouseEvent):void{
			this.tempElement = null;
			this.tempStart.visible = false;
			this.tempEnd.visible = false;
			this.tempTask.visible = false;
			this.tempProc.visible = false;
			this.tempLink.visible = false;
			if(event.target != null && event.target is BorderContainer){
				this.selectRect.visible = false;
			}
		}
		
		protected function diagramMouseClickHandler(event:MouseEvent):void{
			if(this.diagramClickSkip){
				this.diagramClickSkip = false;
				return;
			}
			var p:Point = this.getDiagramPoint(event);
			this.currentElement = this.getPointElement(p);
			if(this.currentElement == null){
				this.unselectAll();
				
			}
			else if(this.currentElement.type == ElementType.LINK){
				this.unselectAll();
				var link:FlowLink = this.currentElement as FlowLink;
				link.changeStatus(p);
			}
			switch(this.status){
				case StatusType.CANVAS_NORMAL:
					break;
				case StatusType.CANVAS_CREATE_ELEMENT:
					var eleType:int = this.controlbar.createElementType;
					switch(eleType){
						case ElementType.START:
						case ElementType.END:
						case ElementType.TASK:
						case ElementType.PROC:
							if(this.tempElement != null){
								var node:WorkNode = new WorkNode(eleType);
								this.addDiagramElement(node);
								node.move(tempElement.x, tempElement.y);
								if(!this.controlbar.isSticky()){
									tempElement.visible = false;
									tempElement = null;
								}
							}
							this.controlbar.refresh();
							break;
						case ElementType.LINK:
							break;
						default:
							this.controlbar.refresh();
							break;
					}
					break;
				default:
					break;
			}			
			this.refresh();
		}
		
		protected function diagramMouseUpHandler(event:MouseEvent):void{
			var p:Point = this.getDiagramPoint(event);
			this.currentElement = this.getPointElement(p);
			this.resizingNode = null;
			this.movingEles.removeAll();
			switch(this.status){
				case StatusType.CANVAS_SELECT_RECT:
					this.selectRect.visible = false;
					this.status = StatusType.CANVAS_NORMAL;
					this.selectInRect(new Rectangle(selectRect.x, selectRect.y, selectRect.width, selectRect.height));
					this.cursor = MouseCursor.AUTO;
					this.diagramClickSkip = true;
					break;
				default:
					break;
			}
			this.refresh();
		}
		
		private function selectInRect(rect:Rectangle):void{
			for(var i:int = 0; i < this.elements.length; i++){
				var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(ele.type == ElementType.LINK){
					var link:FlowLink = ele as FlowLink;
					if(rect.contains(link.x + link.xFrom, link.y + link.yFrom) && rect.contains(link.x + link.xTo, link.y + link.yTo)){
						link.status = StatusType.LINE_SELECT;
					}
					else{
						link.status = StatusType.LINE_NORMAL;
					}
				}
				else{
					var node:WorkNode = ele as WorkNode;
					if(rect.containsPoint(node.getCenterPoint())){
						node.status = StatusType.NODE_SELECT;
					}
					else{
						node.status = StatusType.NODE_NORMAL;
					}
				}
			}
		}
		
		
		protected function diagramMouseMoveHandler(event:MouseEvent):void{
			this.cursor = MouseCursor.AUTO;
			var p:Point = this.getDiagramPoint(event);
			this.currentElement = this.getPointElement(p);
			if(this.currentElement != null){
				this.cursor = this.currentElement.cursor;
			}
			switch(this.status){
				case StatusType.CANVAS_NORMAL:
					if(event.buttonDown){
						if(this.resizingNode != null){
							switch(this.resizingNode.status){
								case StatusType.NODE_RESIZING:
									var node:WorkNode = this.resizingNode as WorkNode;
									switch(this.resizingNode.anchor){
										case AnchorType.TOPLEFT:
											cursor = MouseCursor.HAND;
											var fix:Point = new Point(node.shape.x + node.shape.width, node.shape.y + node.shape.height);
											this.resizingNode.move(p.x, p.y);
											this.resizingNode.width = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											if(node.type == ElementType.START || node.type == ElementType.END){
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											}
											else{
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinHeight, Math.abs(p.y - fix.y));
											}									
											break;
										case AnchorType.TOPRIGHT:
											cursor = MouseCursor.HAND;
											fix = new Point(node.shape.x, node.shape.y + node.shape.height);
											this.resizingNode.move(fix.x, p.y);
											this.resizingNode.width = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											if(node.type == ElementType.START || node.type == ElementType.END){
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											}
											else{
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinHeight, Math.abs(p.y - fix.y));
											}
											break;
										case AnchorType.BOTTOMLEFT:
											cursor = MouseCursor.HAND;
											fix = new Point(node.shape.x + node.shape.width, node.shape.y);
											this.resizingNode.move(p.x, fix.y);
											this.resizingNode.width = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											if(node.type == ElementType.START || node.type == ElementType.END){
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											}
											else{
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinHeight, Math.abs(p.y - fix.y));
											}
											break;
										case AnchorType.BOTTOMRIGHT:
											cursor = MouseCursor.HAND;
											fix = new Point(node.shape.x, node.shape.y);
											this.resizingNode.width = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											if(node.type == ElementType.START || node.type == ElementType.END){
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinWidth, Math.abs(p.x - fix.x));
											}
											else{
												this.resizingNode.height = Math.max(this.resizingNode.explicitMinHeight, Math.abs(p.y - fix.y));
											}
											break;
										default:
											break;
									}
									break;
								default:
									break;
							}
						}						
					}
					break;
				case StatusType.CANVAS_SELECT_RECT:
					if(event.buttonDown){						
						var srx:Number = Math.min(p.x, selectStartPoint.x);
						var sry:Number = Math.min(p.y, selectStartPoint.y);
						var srw:Number = Math.abs(p.x - selectStartPoint.x);
						var srh:Number = Math.abs(p.y - selectStartPoint.y);
						
						this.selectRect.visible = true;
						this.selectRect.x = srx;
						this.selectRect.y = sry;
						this.selectRect.width = srw;
						this.selectRect.height = srh;
						
						//trace("rect: " + srx + "," + sry + " [" + srw + "," + srh + "]");
						this.cursor = MouseCursor.HAND;
					}
					break;
				case StatusType.CANVAS_CREATE_ELEMENT:
					if(this.tempElement != null){
						if(this.tempElement.type == ElementType.LINK){
							this.tempLink.mousePoint = p;
						}
						else{
							this.tempElement.move(p.x - this.tempElement.width/2, p.y - this.tempElement.height/2);
						}						
					}
					break;
				default:
					break;
			}
			this.refresh();
		}
		
		protected function refresh():void{
			for(var i:int = 0; i < this.elements.length; i++){
				var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
				ele.refresh();
			}
		}
		
		protected function diagramKeyUpHandler(event:KeyboardEvent):void{
			switch(event.keyCode){
				case 37: //arrow left
					moveElements(-1,0,0,0);
					break;
				case 38: //arrow top
					moveElements(0,-1,0,0);
					break;
				case 39: //arrow right
					moveElements(0,0,1,0);
					break;
				case 40: //arrow down
					moveElements(0,0,0,1);
					break;
				case 46: //delete
					deleteElements();
					break;
				default:
					break;
			}
			this.refresh();
		}
		
		protected function moveElements(left:int, top:int, right:int, down:int):void{
			var selected:ArrayCollection = this.getSelectedElements();
			if(selected.length == 0)
				return;
			for(var i:int = 0; i < selected.length; i++){
				var ele:BaseElement = selected.getItemAt(i) as BaseElement;
				var x:Number = ele.x + left + right;
				var y:Number = ele.y + top + down;
				ele.move(x,y);
			}
			
		}
		
		protected function deleteElements():void{
			var selected:ArrayCollection = this.getSelectedElements();
			if(selected.length == 0)
				return;
			Alert.show("您确定要删除选中的元素吗？", "删除", Alert.YES | Alert.NO, this.diagram, onDeleteElements);
		}
		
		private function onDeleteElements(event:CloseEvent):void{
			if(event.detail == Alert.YES){
				var selected:ArrayCollection = this.getSelectedElements();
				var map:Object = new Object();
				for(var i:int = 0; i < selected.length; i++){
					var ele:BaseElement = selected.getItemAt(i) as BaseElement;
					if(map.hasOwnProperty(ele.id))
						continue;
					map[ele.id] = ele;					
					if(ele.type == ElementType.LINK)
						continue;
					var node:WorkNode = ele as WorkNode;
					for(var k:int = 0; k < node.inputLinks.length; k ++){
						var link:FlowLink = node.inputLinks.getItemAt(k) as FlowLink;
						if(map.hasOwnProperty(link.id))
							continue;
						map[link.id] = link;
						selected.addItem(link);
					}
					for(k = 0; k < node.outputLinks.length; k++){
						link = node.outputLinks.getItemAt(k) as FlowLink;
						if(map.hasOwnProperty(link.id))
							continue;
						map[link.id] = link;
						selected.addItem(link);
					}
				}
				for(i = 0; i < selected.length; i++){
					ele = selected.getItemAt(i) as BaseElement;
					this.delDiagramElement(ele);
				}
			}
		}
		
		public function getSelectedElements():ArrayCollection{
			var selected:ArrayCollection = new ArrayCollection();
			for(var i:int = 0; i < this.elements.length; i++){
				var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(ele.type == ElementType.LINK){
					if(ele.status == StatusType.LINE_SELECT){
						selected.addItem(ele);
					}
				}
				else{
					if(ele.status == StatusType.NODE_SELECT){
						selected.addItem(ele);
					}
				}
			}
			return selected;
		}
		
		protected function diagramDragEnterHandler(event:DragEvent):void
		{
			if(event.dragSource.hasFormat("dragPoint")){
				DragManager.acceptDragDrop(event.currentTarget as BorderContainer);
			}
		}
		
		protected function diagramDragDropHandler(event:DragEvent):void
		{
			if(event.dragInitiator is WorkNode){
				var node:WorkNode = event.dragInitiator as WorkNode;
				var p:Point = this.getDiagramPoint(event);
				if(event.dragSource.hasFormat("dragPoint")){
					var q:Point = event.dragSource.dataForFormat("dragPoint") as Point;
					node.move(Math.max(0, p.x - q.x), Math.max(0, p.y - q.y));
					node.status = StatusType.NODE_HOVER;
				}
			}
		}
		
		public function getDefaultElementName(nodeType:int):String{
			var nodeName:String;
			switch(nodeType){
				case ElementType.START:
					nodeName = "开始";
					break;
				case ElementType.END:
					nodeName = "结束";
					break;
				case ElementType.PROC:
					var maxidx:int = 1;
					var curidx:int = 1;
					for(var i:int = 0; i < this.elements.length; i++){
						var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
						if(ElementType.PROC != ele.type)
							continue;
						var matches:Array = ele.name.match(subProcessDefaultNamePtn);
						if(matches == null)
							continue;
						curidx = int(matches[1]);
						if(curidx >= maxidx)
							maxidx = curidx + 1;
					}
					nodeName = "子流程" + maxidx;
					break;
				case ElementType.TASK:
					maxidx = 1;
					curidx = 1;
					for(i = 0; i < this.elements.length; i++){
						ele = this.elements.getItemAt(i) as BaseElement;
						if(ElementType.TASK != ele.type)
							continue;
						matches = ele.name.match(normalTaskDefaultNamePtn);
						if(matches == null)
							continue;
						curidx = int(matches[1]);
						if(curidx >= maxidx)
							maxidx = curidx + 1;
					}
					nodeName = "任务" + maxidx;
					break;		
				default:
					nodeName = "";
					break;
			}
			return nodeName;
		}
		
		public function addDiagramElement(ele:BaseElement, temp:Boolean = false):void{
			ele.setParent(this);
			if(!temp){
				this.elements.addItem(ele);
			}
			this.diagram.addElement(ele);
		}
		
		public function delDiagramElement(ele:BaseElement):void{
			if(ele.type == ElementType.LINK){
				FlowLink(ele).startNode = null;
				FlowLink(ele).endNode = null;
			}
			else{
				WorkNode(ele).inputLinks.removeAll();
				WorkNode(ele).outputLinks.removeAll();
			}
			for(var i:int = 0; i < this.elements.length; i++){
				var base:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(ele.id == base.id){
					this.elements.removeItemAt(i);
					break;
				}
			}
			this.diagram.removeElement(ele);
		}
		
		public function getDiagramPoint(event:MouseEvent):Point{
			var p:Point = new Point(0, 0);
			var base:Point = this.diagram.localToGlobal(p);
			p.x = event.stageX - base.x;
			p.y = event.stageY - base.y;
			return p;
		}
		
		private function createTestElements():void{
			var node:WorkNode = new WorkNode();
			node.left = 200;
			node.top = 200;
			this.addDiagramElement(node);
			
			node = new WorkNode(ElementType.PROC);
			node.left = 400;
			node.top = 400;
			this.addDiagramElement(node);
			
			node = new WorkNode(ElementType.START);
			node.left = 100;
			node.top = 300;
			this.addDiagramElement(node);
			
			node = new WorkNode(ElementType.END);
			node.left = 200;
			node.top = 300;
			this.addDiagramElement(node);
		}
		
		public function unselectAll(exceptId:String = null):void{
			trace("un select");
			if(this.controlbar.isSticky())
				return;
			for(var i:int = 0; i < this.elements.length; i++){
				var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(ele.id == exceptId)
					continue;
				if(ele is WorkNode){
					ele.status = StatusType.NODE_NORMAL;
				}
				else if(ele is FlowLink){
					ele.status = StatusType.LINE_NORMAL;
				}
			}
		}
		
		public function getPointElement(p:Point, exceptId:String = null):BaseElement{
			var targetEle:BaseElement = null;
			for(var i:int = 0; i < this.elements.length; i++){
				var ele:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(ele.id == exceptId)
					continue;
				var rect:Rectangle = new Rectangle(ele.x, ele.y, ele.width, ele.height);
				if(rect.containsPoint(p)){
					targetEle = ele;
					break;
				}
			}
			return targetEle;
		}
		
		public function onSticky():Boolean{
			return false;
		}
		
		private function deleteElement(ele:BaseElement):void{
			if(ele == null)
				return;
			var idx:int = -1;
			for(var i:int = 0; i < this.elements.length; i++){
				var item:BaseElement = this.elements.getItemAt(i) as BaseElement;
				if(item.id == ele.id){
					idx = i;
					break;
				}
			}
			if(idx >= 0)
				this.elements.removeItemAt(idx);
		}
		
//		public function snapshoot(ele:BaseElement):UIComponent{
//			var bmd:BitmapData = new BitmapData(ele.width, ele.height);
//			bmd.draw(ele, new Matrix());
//			
//			var dragImg:UIComponent = new UIComponent();
//			
//			dragImg.addChild(new Bitmap(bmd));
//			return dragImg;
//		}
		
		public function createLinkByTemp():void{
			if(this.tempLink.startNode == null || this.tempLink.endNode == null)
				return;
			var link:FlowLink = new FlowLink();
			this.addDiagramElement(link);
			link.setEndPoints(this.tempLink.startNode, this.tempLink.endNode);
			this.tempLink.clearEndPoints();
			this.tempLink.status = StatusType.LINE_SAMPLE;
			this.tempLink.visible = false;
			link.startNode.outputLinks.addItem(link);
			link.endNode.inputLinks.addItem(link);
			this.controlbar.refresh();
		}
	}
}